package com.durian.base.net.request;


import androidx.lifecycle.Lifecycle;
import androidx.collection.ArrayMap;

import com.durian.base.net.HttpConfig;
import com.durian.base.net.HttpRequestParams;
import com.durian.base.net.HttpResponse;
import com.durian.base.net.HttpTaskManager;
import com.durian.base.net.IHttpTask;
import com.durian.base.net.Utils;
import com.durian.base.net.cache.IHttpCacheManager;
import com.durian.base.net.listener.OnLoadListener;
import com.durian.base.net.monitor.HttpMonitor;
import com.durian.base.net.monitor.HttpMonitorListener;
import com.durian.base.utils.GsonUtils;
import com.durian.base.utils.MD5;

import java.io.File;
import java.net.SocketTimeoutException;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import okhttp3.Call;
import okhttp3.Request;


/**
 * 说明：OkHttpTask
 * <p/>
 * 作者：fanly
 * <p/>
 * 类型：Class
 * <p/>
 * 时间：2019/1/31 11:32
 * <p/>
 * 版本：version 1.0
 */
public abstract class OkHttpTask extends AbstractHttpTask {

    protected OnLoadListener    mOnLoadListener;
    protected HttpRequestParams mRequestParams;
    protected Call              mCall;
    protected long              timeOut = HttpConfig.Constant.TIME_OUT;

    public OkHttpTask(Lifecycle lifecycle, String url) {
        super(lifecycle, url);
    }

    private OkHttpTask checkRequestParams(){
        if (mRequestParams == null){
            if (HttpConfig.get().getDefultRequestFactroy() != null){
                mRequestParams = HttpConfig.get().getDefultRequestFactroy().createRequest().getHttpRequestParams();
            }
            if (mRequestParams == null){
                mRequestParams = new HttpRequestParams();
            }
        }
        return this;
    }

    @Override
    protected void doHttpMonitorRequest() {
        super.doHttpMonitorRequest();
        ArrayMap<HttpMonitorListener, HttpMonitorListener> monitorMap = HttpMonitor.get().getMonitorMap();
        if (monitorMap != null) {
            for (Map.Entry<HttpMonitorListener, HttpMonitorListener> entry : monitorMap.entrySet()) {
                entry.getKey().request(this);
            }
        }
    }

    @Override
    protected void doHttpMonitorResponse(HttpResponse response) {
        super.doHttpMonitorResponse(response);
        response.setTaskId(taskId);
        response.setUrl(url);
        response.setRequestParams(mRequestParams);
        ArrayMap<HttpMonitorListener, HttpMonitorListener> monitorMap = HttpMonitor.get().getMonitorMap();
        if (monitorMap != null) {
            for (Map.Entry<HttpMonitorListener, HttpMonitorListener> entry : monitorMap.entrySet()) {
                entry.getKey().response(response);
            }
        }
    }

    protected OnLoadListener getOnLoadListener(){
        return mOnLoadListener;
    }

    public OkHttpTask setOnLoadListener(OnLoadListener listener) {
        mOnLoadListener = listener;
        return this;
    }

    /**
     * 单位秒
     *
     * @param timeOut
     * @return
     */
    public OkHttpTask setTimeOut(int timeOut) {
        doSetTimeOut(timeOut);
        return this;
    }

    @Override
    public IHttpTask start() {
        HttpTaskManager.get().addTask(this);
        return this;
    }

    /**
     * 创建 Request.Builder
     *
     * @return
     */
    public abstract Request.Builder createRequestBuilder();

    protected void doSetTimeOut(long timeOut) {
        this.timeOut = timeOut;
    }

    @Override
    protected HttpResponse doInBackground() {
        try {
            Request.Builder builder = createRequestBuilder();
            if (builder == null){
                return HttpResponse.nullResponse();
            }else {
                if (timeOut == HttpConfig.Constant.TIME_OUT) {
                    mCall = HttpConfig.get().client().newCall(builder.build());
                } else {
                    mCall = HttpConfig.get().client().newBuilder().readTimeout(timeOut, TimeUnit.SECONDS).writeTimeout(timeOut, TimeUnit.SECONDS).connectTimeout(timeOut, TimeUnit.SECONDS).retryOnConnectionFailure(true).build().newCall(builder.build());
                }
                return HttpResponse.response(mCall.execute());
            }
        } catch (Exception e) {
            Utils.eLog(e);
            if (e instanceof SocketTimeoutException || (e != null && e instanceof InterruptedException && (e.getMessage() != null && "timeout".equals(e.getMessage().toLowerCase())))) {
                return HttpResponse.timeOut(e);
            } else {
                return HttpResponse.unkown(e);
            }
        }
    }

    @Override
    protected void doCancelTask() {
        super.doCancelTask();
        if (mCall != null && !mCall.isCanceled()) {
            try {
                mCall.cancel();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * Params
     **/

    public OkHttpTask setReqeust(IBaseRequest baseRequest) {
        if (baseRequest != null) {
            mRequestParams = baseRequest.getHttpRequestParams();
        }
        return this;
    }

    public OkHttpTask putParams(String key, int value) {
        checkRequestParams();
        mRequestParams.putParams(key, value);
        return this;
    }

    public OkHttpTask putParams(String key, int value,boolean isAdd) {
        checkRequestParams();
        if (isAdd){
            mRequestParams.putParams(key, value);
        }
        return this;
    }

    public OkHttpTask putParams(String key, double value) {
        checkRequestParams();
        mRequestParams.putParams(key, value);
        return this;
    }

    public OkHttpTask putParams(String key, boolean value) {
        checkRequestParams();
        mRequestParams.putParams(key, value);
        return this;
    }

    public OkHttpTask putParams(String key, long value) {
        checkRequestParams();
        mRequestParams.putParams(key, value);
        return this;
    }

    public OkHttpTask putParams(String key, String value) {
        checkRequestParams();
        if (value != null){
            mRequestParams.putParams(key, value);
        }
        return this;
    }

    public OkHttpTask putFile(String key, File file) {
        checkRequestParams();
        mRequestParams.putFile(key, file);
        return this;
    }

    public OkHttpTask putFile(String key, File file, String contentType) {
        checkRequestParams();
        mRequestParams.putFile(key, file, contentType);
        return this;
    }

    public OkHttpTask putFiles(String key, List<File> files) {
        checkRequestParams();
        mRequestParams.putFiles(key, files);
        return this;
    }

    /**
     * Header
     **/
    public OkHttpTask putHeader(String key, int value) {
        checkRequestParams();
        mRequestParams.putHeader(key, value);
        return this;
    }

    public OkHttpTask putHeader(String key, double value) {
        checkRequestParams();
        mRequestParams.putHeader(key, value);
        return this;
    }

    public OkHttpTask putHeader(String key, String value) {
        checkRequestParams();
        mRequestParams.putHeader(key, value);
        return this;
    }

    public OkHttpTask setCacheKey(String cacheKey){
        this.cacheKey = cacheKey;
        return this;
    }

    @Override
    public String getCacheKey() {
        return MD5.getMD5(cacheKey+ GsonUtils.toJson(getRequestParams()));
    }

    @Override
    public IHttpCacheManager getHttpCacheManager() {
        return mHttpCacheManager;
    }

    public OkHttpTask setCacheManager(IHttpCacheManager manager){
        this.mHttpCacheManager = manager;
        return this;
    }

    public HttpRequestParams getRequestParams() {
        checkRequestParams();
        return mRequestParams;
    }

    @Override
    public String getCacheUrl() {
        return url;
    }

}
